#include "form_qst.h"
#include "ui_form_qst.h"


Form_qst::Form_qst(QWidget *parent) : QWidget(parent), ui(new Ui::Form_qst) {
    ui->setupUi(this);
}

/**
 * @brief Form_qst::点击关闭按钮
 * @param event 关闭事件
 */
void Form_qst::closeEvent(QCloseEvent* event){

    int ign = 0;        //是否需要忽略信号

    if(isEditor){
        //编辑模式

        if(isChanged){
            //文件发生修改
            auto ret = QMessageBox::warning(0,"您确定要退出？","如果不进行保存，您的文本将会丢失",QMessageBox::Close | QMessageBox::Save | QMessageBox::Discard);
            if(ret == QMessageBox::Save){
                //保存文件
                saveqst_ed();
            }else if (ret == QMessageBox::Close){
                //忽略关闭信号
                ign = 1;
            }
        }


    }else{
        //做题模式
        if(ui->tree_ans->isEnabled()){
            //如果没提交
            auto ret = QMessageBox::warning(0,"您确定要退出？","如果不进行提交，您的作答将会作废",QMessageBox::Yes | QMessageBox::No);
            if(ret != QMessageBox::Yes)ign = 1;
            else stopTick_ans();
        }else{
            stopTick_ans();
        }

    }

    if(ign){
        //忽略
        event->ignore();
    }else{
        //否则发送信号
        emit qsted_closed();

    }


}

Form_qst::~Form_qst() {
    delete ui;
}

/**
 * @brief Form_qst::传递用户信息
 * @param s     设置信息
 * @param inf   登录信息
 */
void Form_qst::setUserMsg(setting* s,loginInfo* inf){
    this->set = *s;
    this->lginfo = *inf;
}


/**
 * @brief Form_qst::设置编辑模式
 */
void Form_qst::setupEditor(){

    setWindowTitle("Editor:untitled1.html");
    addMainqst_ed();
    addqst_ed();
    whenStart.setHMS(0,0,0);
    timeLimit.setHMS(0,0,0);
    isEditor = 1;

    ui->stackedWidget->setCurrentIndex(0);
    ui->stackedWidget_2->setCurrentIndex(1);
    ui->but_back->setText("返回");
    ui->but_next->setDisabled(1);
}


/**
 * @brief Form_qst::做题模式
 */
void Form_qst::setupAnswer(){

    setWindowTitle("Question");
    whenStart.setHMS(0,0,0);
    timeLimit.setHMS(0,0,0);
    isEditor = 0;

    ui->but_back->setText("上一题");

    //暂不支持
    ui->but_back->setEnabled(0);
    ui->but_next->setEnabled(0);

    ui->but_calc->setDisabled(0);
}


/**
 * @brief Form_qst::以新建方式打开编辑器
 */
void Form_qst::newQEditor(){
    setupEditor();
    on_but_new_clicked();
    this->show();
}

/**
 * @brief Form_qst::以路径打开题目
 * @param mpath 文件路径
 * @param mode 模式 0表示做题器 1表示编辑器
 */
void Form_qst::openQPath(QString mpath,bool mode){

    if(mode){
        setupEditor();                  //设置编辑器
        openqst_ans(mpath);             //将题目数据读入
    }else{
        setupAnswer();                  //设置做题器
        openqst_ans(mpath);             //将题目数据读入
        on_but_cin_clicked();           //转至做题视图
    }

    this->show();
}

void Form_qst::openQDlg(bool mode){

    openqst_ed();

    this->show();
}


//===============================================================================================================================================
//      内部使用
//===============================================================================================================================================



/**
 * @brief Form_qst::根据题目路径打开题目文件
 * @param mpath 题目路径
 */
void Form_qst::openqst_ans(QString mpath){

    clearAll();

    if(!mpath.isEmpty()){

        QFile file(mpath);

        if(!file.open(QIODevice::ReadOnly)){
            QMessageBox::critical(0,"提示","文件打开失败！\n" + mpath);
            return;
        };
        QTextStream qstream(&file);
        ui->text_material->setPlainText(qstream.readAll());
        ui->txtB_main->setHtml(ui->text_material->toPlainText());
        ui->tree_add->setDisabled(1);
        file.close();

        this->path = mpath;
    }

}

/**
 * @brief Form_qst::有文件对话框打开题目文件
 */
void Form_qst::openqst_ed(){
    QString p;
    GETQSTRWS(2*FILENAME_MAX,p,this->set.problemfd);
    path = QFileDialog::getOpenFileName(0,"打开文件",p,"*.html");
    openQPath(path,1);
}


/**
 * @brief Form_qst::检查题目内容
 * @return 是否成功
 */
int Form_qst::checkqst_ed(){
    numqst_ans = ui->tree_add->topLevelItemCount(); //小题数
    if(numqst_ans <= 1){
        QMessageBox::warning(0,"提示","目前没有题目");
        return 0;
    }
    for(int i = 1;i < numqst_ans;++i){
        //遍历
        auto tp = ui->tree_add->topLevelItem(i);
        if(!tp)break;   //删完就走
        auto fst = tp->child(0);
        auto th = (QTextEdit*)ui->tree_add->itemWidget(fst,1);
        auto txt = (QTextEdit*)ui->tree_add->itemWidget(fst,3);
        if(txt->toPlainText() == ""){
            //题目内容为空
            QMessageBox::warning(0,"提示",QString("第%1小题没有题干，将自动删除").arg(th->toPlainText().toInt()));
            ui->tree_add->takeTopLevelItem(i);  //删除题目
            i--;    //删除滞后
        }
    }
    numqst_ans = ui->tree_add->topLevelItemCount();
    if(numqst_ans <= 1){
        QMessageBox::warning(0,"提示","目前没有题目");
        return 0;
    }
    showqsthmp_ans(1);      //显示答案
    return 1;
}

/**
 * @brief Form_qst::保存编辑的文件
 */
void Form_qst::saveqst_ed(){

    path = QFileDialog::getSaveFileName(0,"保存文件",problem_title,"*.html");

    if(!path.isEmpty()){
        int ret = save_file_string(path,ui->text_material->toPlainText());    //保存文件内容
        if(!ret)return; //文件保存失败则退出
        QMessageBox::information(0,"保存文件","文件已经成功保存");
        setWindowTitle(QString("Editor:") + path);
        isChanged = 0;
    }


}

/**
 * @brief Form_qst::添加题目的题干信息
 */
void Form_qst::addMainqst_ed(){

    ui->tree_add->setColumnCount(7);


    auto nitem = new QTreeWidgetItem(QStringList{"操作","题目标题","考点类别","题干文字","题目编号","满分","限时"});
    ui->tree_add->addTopLevelItem(nitem);
    auto witem = new QTreeWidgetItem();
    nitem->addChild(witem);

    setTextBoxLine_tree(ui->tree_add,witem);    //设置一行的文本框

    but_append = new QPushButton("添加");
    but_append->setIcon(QIcon(":/new/prefix1/rc/open1.png"));
    ui->tree_add->setItemWidget(witem,0,but_append);
    connect(but_append,&QPushButton::pressed,this,&Form_qst::onclick_but_append);


    auto nTBox3 = (QTextEdit*)ui->tree_add->itemWidget(witem,1);//题目标题
    connect(nTBox3,&QTextEdit::textChanged,this,&Form_qst::onchange_TreeCtrlTitle);
    //nTBox3->installEventFilter(this);

    auto nCBox = new QComboBox();               //考点类别
    nCBox->addItems(QStringList{"语法","阅读理解","听力","单词","写作","翻译","综合"});
    ui->tree_add->setItemWidget(witem,2,nCBox);
    connect(nCBox,&QComboBox::currentTextChanged,this,&Form_qst::onchange_TreeCtrlText);

    auto nTBox2 = (QTextEdit*)ui->tree_add->itemWidget(witem,3);
    connect(nTBox2,&QTextEdit::textChanged,this,&Form_qst::onchange_TreeCtrlText);

    auto nTBox5 = (QTextEdit*)ui->tree_add->itemWidget(witem,5);
    nTBox5->setEnabled(0);

    auto nTime1 = new QTimeEdit;
    nTime1->setDisplayFormat("HH:mm:ss");
    ui->tree_add->setItemWidget(witem,6,nTime1);
    connect(nTime1,&QTimeEdit::timeChanged,this,&Form_qst::onchange_TreeCtrlTimeEdit);

    ui->tree_add->expandItem(nitem);
    //展开

}

/**
 * @brief Form_qst::读取问题文件 装入做题栏
 */
void Form_qst::addqst_ans(){
    ui->tree_ans->clear();
    lst_ans.clear();

    try {
        //只要throw了说明文件有误 都不可以进行读取

        QList<QString> lst = ui->text_material->toPlainText().split(htmlsplitQA());
        //lst[0]题干
        //lst[1]答案
        //（1）,选择题,A,8分
        if(lst.size() < 2)throw 1;
        QList<QString> line = lst[1].split("<1><br>");
        QList<QTreeWidgetItem*> qt;

        auto it = line.begin();
        //
        //第一行：<p class="ans">限时(04:00:00)参考答案：
        QString t = it->mid(20,8);
        QList<QString> hms = t.split(":");
        if(hms.size() < 3)throw 1;
        isTicked = (t != "00:00:00");
        timeLimit.setHMS(hms[0].toInt(),hms[1].toInt(),hms[2].toInt()); //提取时间限制
        timeleft = QTime(0,0,0).secsTo(timeLimit);

        ++it;

        for(int i = 1;i < line.count()-1;++i){
            auto ans = it->split("<br><0>");
            lst_ans.push_back(ans);
            if(ans.size() < 2)throw 1;
            auto t = new QTreeWidgetItem({ans[0],ans[1]});
            qt.push_back(t);
            it++;
        }

        ui->tree_ans->setColumnCount(2);
        ui->tree_ans->addTopLevelItems(qt);

        //设置控件
        for(int i = 0;i < ui->tree_ans->topLevelItemCount();++i){
            auto tt = ui->tree_ans->topLevelItem(i);

            if(tt->text(1) == "判断题"){
                auto cbo = new QComboBox();
                cbo->addItems(QList<QString>{"","T","F"});
                cbo->setFixedHeight(40);
                ui->tree_ans->setItemWidget(tt,1,cbo);
            }else if(tt->text(1) == "选择题"){
                auto txt = new QTextEdit;
                txt->setPlaceholderText("输入您的答案");
                txt->setFixedHeight(40);
                ui->tree_ans->setItemWidget(tt,1,txt);
            }else{
                auto txt = new QTextEdit;
                txt->setPlaceholderText("输入您的答案");
                txt->setFixedHeight(160);
                ui->tree_ans->setItemWidget(tt,1,txt);

            }


        }
    } catch (int) {
        //有问题
        ui->tree_ans->clear();
        ui->tree_ans->setColumnCount(1);
        ui->tree_ans->addTopLevelItem(new QTreeWidgetItem({"无法读取题目信息！检查题目格式是否正确！"}));
        lst_ans.clear();
    }




}

/**
 * @brief Form_qst::添加一组题目编辑
 */
void Form_qst::addqst_ed(){
    int row = ui->tree_add->topLevelItemCount();  //当前行
    auto topitem = ui->tree_add->topLevelItem(row-1);
    int lastcboindex = 0;                         //记录下题目类型的索引
    if(row >= 2){
        auto k = (QComboBox*)ui->tree_add->itemWidget(topitem->child(0),2);
        if(k)lastcboindex = k->currentIndex();
    }
    noqst++;

    QList<QString> ql = {"操作","小题号 " + QString::number(noqst),"问题类别","问题文字","可选答案","正确答案","正确分数"};

    auto nitem = new QTreeWidgetItem(ql);
    ui->tree_add->addTopLevelItem(nitem);

    auto witem = new QTreeWidgetItem();
    nitem->addChild(witem);
    setTextBoxLine_tree(ui->tree_add,witem);

    auto nButDel = new QPushButton("删除");
    nButDel->setIcon(QIcon(":/new/prefix1/rc/del1.png"));
    nButDel->setObjectName("TreeCtrlDel" + QString::number(row));
    //统一名TreeCtrlDel + 行号
    ui->tree_add->setItemWidget(witem,0,nButDel);
    connect(nButDel,&QPushButton::pressed,this,&Form_qst::onclick_TreeCtrlDel);
    //先统一链接到一个槽函数 到时候一起判断


    auto nCBox = new QComboBox();
    nCBox->addItems(QStringList{"判断题","选择题","填空题","问答题"});
    nCBox->setCurrentIndex(lastcboindex);
    ui->tree_add->setItemWidget(witem,2,nCBox);

    //统一名TreeCtrlCombo + 新题号
    nCBox->setObjectName("TreeCtrlCombo" + QString::number(noqst) );
    //链接组合框

    connect(nCBox,&QComboBox::currentTextChanged,this,&Form_qst::onchange_TreeCtrlCombo);

    //链接文本框
    auto nTBox1 = (QTextEdit*)ui->tree_add->itemWidget(witem,1);
        //widget --> textedit
    nTBox1->setText(QString::number(noqst));
    nTBox1->setObjectName("TreeCtrlSmallNo" + QString::number(noqst));
    connect(nTBox1,&QTextEdit::textChanged,this,&Form_qst::onchange_TreeCtrlSmallNo);
    //统一名TreeCtrlSmallNo + 新题号

    auto nTBox2 = (QTextEdit*)ui->tree_add->itemWidget(witem,3);
    nTBox2->setObjectName("TreeCtrlText"+ QString::number(noqst));
    //nTBox2->installEventFilter(this);
    //统一名TreeCtrlText + 新题号
    connect(nTBox2,&QTextEdit::textChanged,this,&Form_qst::onchange_TreeCtrlText);

    auto nTBox3 = (QTextEdit*)ui->tree_add->itemWidget(witem,4);
    nTBox3->setObjectName("TreeCtrlTextOption" + QString::number(noqst));
    //统一名TreeCtrlTextOption + 新题号
    nTBox3->setText("T,F");nTBox3->setDisabled(1);

    auto nTBox5 = (QTextEdit*)ui->tree_add->itemWidget(witem,5);
    connect(nTBox5,&QTextEdit::textChanged,this,&Form_qst::onchange_TreeCtrlText);

    auto nTBox6 = (QTextEdit*)ui->tree_add->itemWidget(witem,6);
    connect(nTBox6,&QTextEdit::textChanged,this,&Form_qst::onchange_TreeCtrlText);

    ui->tree_add->expandItem(nitem);
}


void Form_qst::htmlToTree_ed(){
    //把html读入tree中
    //QString str = ui->txtB_main->toPlainText();//转化为txt


}


QString Form_qst::htmlheader_ans(){

    return R"(
    <!---题目编辑器V0.1使用说明---->
    <!---题目的题干由一个HTML文档排版 可以直接编辑HTML文件在块中添加文字 ----->
    <!---也可以通过右侧的输入框 进行题目编写-->
    <!---限时调为00:00:00代表不计时--->
    <!---style样式: 设置块的排版-->
    <!---h1：center样式: 标题-->
    <!---p：main样式: 正文段落 (按回车以分段)-->
    <!---p：qst样式: 问题段落 (一小题一段)-->
    <!---p：ans样式: 答案段落 (一小题一段)-->
    <style>
    h1.center
    {
        text-align: center;
    }

    p.main
    {
        text-indent: 40px;
        font-family: 'Times New Roman', Times, serif;
        text-align: justify;
        font-size: 18px;
    }

    p.qst
    {
        font-size: 16px;
        font-family:"Microsoft YaHei";
    }

    p.ans
    {
        font-size: 16px;
        font-family: 'Courier New', Courier, monospace;
    }

    </style>
    )";         //定义style
}

QString Form_qst::htmlfmth1_ans(){

    return "\n<h1 class = \"center\">\n%1\n</h1>\n";
}

QString Form_qst::htmlfmtMain_ans(){
    return "\n<p class=\"main\">\n%1\n</p>\n";
}

QString Form_qst::htmlfmtqst_ans(){
    return "\n<p class=\"qst\">\n%1\n</p>\n";
}

QString Form_qst::htmlfmtans_ans(){
    return "\n<p class=\"ans\">\n%1\n</p>\n";
}

QString Form_qst::htmlfmthide_ans(){
    return "\n<p class=\"hidden\">\n%1\n</p>\n";
}

QString Form_qst::htmlTab(){
    return QString("&nbsp;").repeated(4);
}

QString Form_qst::htmlsplitQA(){
    return htmlfmthide_ans().arg("————————————————————分割线————————————————————");
}

/**
 * @brief Form_qst::编辑器数据转化为HTML排版
 * @return html源码
 */
QString Form_qst::turnTohtml(){

    auto fst = ui->tree_add->topLevelItem(0)->child(0);
    QTextEdit* txtT;
    auto cboK = (QComboBox*)ui->tree_add->itemWidget(fst,2);
    auto txtM = (QTextEdit*)ui->tree_add->itemWidget(fst,3);
    QString res;

    QString fmtheader;    //样式格式
    fmtheader = htmlheader_ans();
    res = fmtheader;

                            //限时和考点
    QString t = timeLimit.toString();
    res += QString("<h3>限时(%1) %2\n</h3>").arg(t == "00:00:00" ? "不限时" : t,cboK->currentText());

    QString h1 = htmlfmth1_ans();   //标题
    h1 = h1.arg(problem_title);

    //标题居中
    res += h1;


    QString mainp = htmlfmtMain_ans();     //正文
    QString str = txtM->toPlainText();
    //每行一段
    QList<QString> rows = str.split("\n");
    foreach(auto &x,rows){
        res += mainp.arg(x);
    }
    //设置中间段

    QString qstp = htmlfmtqst_ans();    //问题
    totalscore = 0;
    for(int i = 1;i < ui->tree_add->topLevelItemCount();++i){
        //遍历...
        fst = ui->tree_add->topLevelItem(i)->child(0);

        auto cbT = (QComboBox*)ui->tree_add->itemWidget(fst,2);
        auto txtN = (QTextEdit*)ui->tree_add->itemWidget(fst,1);
        auto txtQ = (QTextEdit*)ui->tree_add->itemWidget(fst,3);
        auto txtF = (QTextEdit*)ui->tree_add->itemWidget(fst,6);
        double curscore = fix_number(txtF->toPlainText().toDouble(),0,SCOREMAX,0);
        totalscore += curscore;

        str = QString("(%1)").arg(QString::number(fix_number(txtN->toPlainText().toInt(),1,SMALLNOMAX,0)))
              + txtQ->toPlainText();
        str = str.replace("\n","<br>\n" + htmlTab());
        str = qstp.arg(str);

        res += QString("<p style=\"font-size:18px\">%1 [本题%2分]</p>\n").arg(
            cbT->currentText(),
            QString::number(curscore)
            );
        res += str;

    }

    str = "";
    QString ansp = htmlfmtans_ans();    //答案

    for(int i = 1;i < ui->tree_add->topLevelItemCount();++i){
        fst = ui->tree_add->topLevelItem(i)->child(0);
        auto cbT = (QComboBox*)ui->tree_add->itemWidget(fst,2);
        auto txtA = (QTextEdit*)ui->tree_add->itemWidget(fst,5);
        auto txtN = (QTextEdit*)ui->tree_add->itemWidget(fst,1);
        auto txtF = (QTextEdit*)ui->tree_add->itemWidget(fst,6);

        str += QString("（%1）<br><0>%3<br><0>%2<br><0>%4分<1><br>").arg(
            QString::number(fix_number(txtN->toPlainText().toInt(),1,SMALLNOMAX,1)),    //小题号
            txtA->toPlainText().replace("\n","<br>"),
            cbT->currentText(),
            QString::number(fix_number(txtF->toPlainText().toDouble(),0,SCOREMAX,1))    //每小题几分
            );
    }


    res += htmlsplitQA();//QT5.12 还没支持hidden 只能这样了.......

    res += ansp.arg(QString("限时(%1)参考答案：<1><br>").arg(t) + str);


    fst = ui->tree_add->topLevelItem(0)->child(0);
    txtT = (QTextEdit*)ui->tree_add->itemWidget(fst,5);
    txtT->setText(QString::number(totalscore));

    return res;
}


/**
 * @brief Form_qst::用编辑器中的数据显示题目数据
 * @param showAns 是否显示答案
 */
void Form_qst::showqsthmp_ans(bool showAns){

    QString full_html = turnTohtml();
    QList<QString> lst = full_html.split(htmlsplitQA());
    //lst[0]题干
    //lst[1]答案
    if(showAns){
        ui->txtB_main->setHtml(full_html);
    }else{
        ui->txtB_main->setHtml(lst[0]);
    }
    ui->text_material->setPlainText(full_html);


}

/**
 * @brief Form_qst::匹配答案
 * @param category 题目种类
 * @param stdansText 标准答案
 * @param myansText 提交答案
 * @return
 */
int Form_qst::match_ans(QString category,QString stdansText,QString myansText){
    int res = 0;
    if(category == "选择题" || category == "判断题"){
        res = stdansText.compare(myansText,Qt::CaseInsensitive) == 0;
    }else{
        res = stdansText.compare(myansText) == 0;
    }

    return res;
}

/**
 * @brief Form_qst::计算分数等数据
 * @details [out]
    double score_ans;   //得分
    int numqst_ans;     //题目数
    int numAC_ans;      //正确
    int numWA_ans;      //做错
    int numTLE_ans;     //没做
    int numNRated_ans;  //没改
 */
void Form_qst::calcscore_ans(){

    lst_nAC.clear();    //错误信息
    lst_allans.clear(); //回答信息

    score_ans = 0,numAC_ans = 0,numWA_ans = 0,numTLE_ans = 0,numNRated_ans = 0;

    numqst_ans = ui->tree_ans->topLevelItemCount();
    auto it = lst_ans.begin();

    for(int i = 0;i < numqst_ans;++i){
        //逐个对答案
        auto fst = ui->tree_ans->topLevelItem(i);

        //对答题控件进行区分
        auto wid = ui->tree_ans->itemWidget(fst,1);
        QString myansText = "未识别";
        QString type = wid->metaObject()->className();
        if(type == "QComboBox"){
            auto t = (QComboBox*)wid;
            myansText = t->currentText();
        }else if(type == "QTextEdit"){
            auto t = (QTextEdit*)wid;
            myansText = t->toPlainText();
        }



        bool right = 0;     //是否正确
        QString descript;   //说明
        QString stdansText; //标准答案
        double ansscore;    //本题得分


        ansscore = it->at(3).chopped(1).toDouble();
        stdansText = it->at(2);

        if(myansText == ""){
            descript = "未答";
            numTLE_ans++;
        }else if(it->at(1) == "问答题"){
            //问答题不改
            descript = "未批改";
            numNRated_ans++;
        }else{

            if(match_ans(it->at(1),stdansText,myansText)){
                //做对了才给分
                descript = "正确";
                score_ans += ansscore;
                right = 1;
                numAC_ans++;
            }else{
                //做错了
                descript = "错误";
                numWA_ans++;
            }
        }

        if(!right){
            //（5）,未批改
            lst_nAC.push_back(QString("%1,%2").arg(fst->text(0),descript));
        }


        //记录回答答案 每一题一行 文字用""包含 统一使用<br>代替换行符
        //格式：题号,题目分数,实际得分,学生答案,正确答案,状态
        lst_allans.push_back(QString("%1,%2,%3,\"%4\",\"%5\",%6\n").arg(
                fst->text(0),
                QString::number(ansscore),
                QString::number(right ? ansscore : 0),
                myansText.replace("\n","<br>"),
                stdansText.replace("\n","<br>"),
                descript
            ));


        ++it;
    }

}


/**
 * @brief Form_qst::获得生成报告内容
 * @details 格式
        <p style="font-size: 16px;font-family: 'Courier New', Courier, monospace;">
            标题：%<br>
            您的成绩是：%分<br>
            用时：%<br>
            本题共%题 满分%分 不正确（含未批改）题目列表：<br>
            \tab（1）,错误<br>
            \tab（3）,未答<br>
            \tab（5）,未批改<br>
            ...<br>
            共正确%题,错误%题....<br>
        </p>
 * @return 生成报告内容
 */
QString Form_qst::report_ans(){
    //生成报告.html

    QString res = R"(<p style="font-size: 16px;font-family: 'Courier New', Courier, monospace;">%1</p>)";
    QString str = R"(
                    标题：%1<br>
                    您的成绩是：%2分<br>
                    用时：%3<br>
                    本题共%4题 满分%5分 不正确（含未批改）题目列表：<br>
                    )";
    str = str.arg(problem_title,
            QString::number(score_ans),
            QTime(0,0,0).addSecs(timeSecUsed).toString(),
            QString::number(numqst_ans),
            QString::number(totalscore)
            );
    auto it = lst_nAC.begin();
    for(;it != lst_nAC.end();++it){
        str.append(htmlTab() + *it + QString("<br>\n"));
    }
    str += QString("共正确%1题,未批改%2题,未做%3题,错误%4题<br>").arg(
        QString::number(numAC_ans),
        QString::number(numNRated_ans),
        QString::number(numTLE_ans),
        QString::number(numWA_ans)
        );
    return res.arg(str);
}


/**
 * @brief Form_qst::获得记录文件内容
 * @details 记录格式
 *      文件名 学生ID+时间.csv
 *      第1行是表头
 *      提交学生学号,提交题目文件,得分,作答时间,用时,小题数,满分,正确题数,未批题数,未答题数,错误题数
 *      第3行也是表头
 *      题号,题目分数(double),实际得分(double),"学生答案","正确答案",状态
 *      统一在文字部分使用<br>替换了\n
 * @return 文件内容
 */
QString Form_qst::record_ans(){


    QString rec = "提交学生学号,提交题目文件,得分,作答时间,用时,小题数,满分,正确题数,未批题数,未答题数,错误题数\n";
    rec += QString("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11\n").arg(
        QString::number(this->lginfo.user.id),
        this->path,
        QString::number(score_ans),
        whenStart.toString(),
        QTime(0,0,0).addSecs(timeSecUsed).toString(),
        QString::number(numqst_ans),
        QString::number(totalscore),
        QString::number(numAC_ans),
        QString::number(numNRated_ans),
        QString::number(numTLE_ans),
        QString::number(numWA_ans)
    );

    rec += "题号,题目分数,实际得分,学生答案,正确答案,状态\n";

    auto it = lst_allans.begin();
    for(;it != lst_allans.end();++it){
        //遍历答案列表
        rec += *it;
    }

    return rec;
}

/**
 * @brief Form_qst::获取记录文件名 时间+标题+学生ID
 * @return 记录文件名
 */
QString Form_qst::rec_fname(){

    return QDate::currentDate().toString("yyyy-MM-dd") + "-" +
           whenStart.toString("HH-mm-ss") + "-" +
           problem_title +
           QString::number(this->lginfo.user.id);
}


/**
 * @brief Form_qst::做题 -- 开始计时
 */
void Form_qst::startTick_ans(){
    //开始计时
    whenStart = QTime::currentTime();
    timer_ans = new QTimer;
    connect(timer_ans,&QTimer::timeout,this,&Form_qst::timeout_Timer_ans);
    ui->time_progress->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
    if(isTicked){
        //如果要倒计时
        ui->time_progress->setRange(0,timeleft);
    }else{
        ui->time_progress->setMaximum(59);
        ui->time_progress->setMinimum(0);
    }

    timer_ans->start(1000);
    able_ans(1);
}

/**
 * @brief Form_qst::做题 -- 停止计时
 */
void Form_qst::stopTick_ans(){
    auto now = QTime::currentTime();
    timeSecUsed = whenStart.secsTo(now);

    timeleft = 0;
    ui->time_progress->setValue(0);
    delete timer_ans;
    timer_ans = 0;
}

/**
 * @brief Form_qst::做题 -- 时间到！
 */
void Form_qst::timeout_ans(){
    QMessageBox::information(0,"时间到！","您现在无法进行作答，而作答记录将会保存");
    able_ans(0);
    stopTick_ans();     //停止计时
    calcscore_ans();    //算分
    save_grd();         //保存记录

}

/**
 * @brief Form_qst::设置能否继续作答
 * @param b
 */
void Form_qst::able_ans(bool b){
    ui->tree_ans->setEnabled(b);
    ui->but_calc->setEnabled(b);
}

/**
 * @brief Form_qst::统统初始化
 */
void Form_qst::clearAll(){

    nopro = 0;
    noqst = 0;
    timeleft = 0;

    isTicked = 0;
    isChanged = 0;
    totalscore = 0;

    whenStart.setHMS(0,0,0);
    timeLimit.setHMS(0,0,0);
    problem_title.clear();


    ui->tree_add->clear();
    ui->text_material->clear();
    ui->txtB_main->clear();

    if(isEditor){
        ui->tree_add->setDisabled(0);
        setWindowTitle("Editor");
        addMainqst_ed();
        addqst_ans();
    }else{

    }

}




//==========================================================================================================================================================================
//                      回调函数
//
//==========================================================================================================================================================================

bool Form_qst::eventFilter(QObject *obj,QEvent *event){
    return QWidget::eventFilter(obj,event);
}

/**
 * @brief Form_qst::showEvent 显示
 * @param e
 */
void Form_qst::showEvent(QShowEvent* e){
    this->setFocus();
}

/**
 * @brief 窗体内按键信息
 * @details:
 *  Ctrl + A 插入
 *
 * @param e 信息
 */
void Form_qst::keyPressEvent(QKeyEvent* e){

    if(e->modifiers() == Qt::ControlModifier){
        //按下ctrl
        switch(e->key()){
        case Qt::Key_A:
            //触发插入快捷键
            onclick_but_append();

            break;
        default:
            break;
        }

    }

}


void Form_qst::timeout_Timer_ans(){
    auto now = QTime::currentTime();
    if(isTicked){
        ui->time_progress->setValue(timeleft);
        ui->time_progress->setFormat(QTime(0,0,0).addSecs(timeleft).toString());
        if(timeleft == 0){
            timeout_ans();
            return;
        }
        timeleft--;
    }else{

        int secs = whenStart.secsTo(now);
        ui->time_progress->setValue(secs%60);
        ui->time_progress->setFormat(QTime(0,0,0).addSecs(secs).toString());
    }
}

void Form_qst::onchange_TreeCtrlTimeEdit(){
    auto sd = (QTimeEdit*)sender();
    timeLimit = sd->time();
    this->showqsthmp_ans(isEditor);
}

void Form_qst::onclick_but_append(){
    addqst_ed();
    this->showqsthmp_ans(isEditor);
}

void Form_qst::onclick_TreeCtrlDel(){
    auto sd = (QPushButton*)sender();
    int x = sd->frameGeometry().x();
    int y = sd->frameGeometry().y();
    auto item = ui->tree_add->itemAt(QPoint(x,y));  //找到这个单元格
    int i = ui->tree_add->indexOfTopLevelItem(ui->tree_add->itemAbove(item));
    //这个单元格上方就是topitem
    ui->tree_add->takeTopLevelItem(i);


    showqsthmp_ans(isEditor);

}


void Form_qst::onchange_TreeCtrlText(){

    //同步
    showqsthmp_ans(isEditor);
}

void Form_qst::onchange_TreeCtrlCombo(){
    QComboBox* qcb = (QComboBox*)sender();
    //TreeCtrlCombo + 新题号
    int id = qcb->objectName().midRef(13).toInt();

    //寻找选项
    QTextEdit *finder = this->findChild<QTextEdit*>("TreeCtrlTextOption" + QString::number(id));
    if(!finder)return;

    if(qcb->currentText() == "判断题"){
        finder->setText("T,F");
        finder->setDisabled(1);
    }else{
        finder->setText("");

        if(qcb->currentText() == "选择题"){
            finder->setEnabled(1);
            finder->setPlaceholderText("如 A,B,C,D");
        }
    }

    this->showqsthmp_ans(isEditor);
}

void Form_qst::onchange_TreeCtrlSmallNo(){
    auto sd = (QTextEdit*)sender();
    int x = sd->frameGeometry().x();
    int y = sd->frameGeometry().y();
    auto item = ui->tree_add->itemAt(QPoint(x,y));  //找到这个单元格

    ui->tree_add->itemAbove(item)->setText(1,"小题号 " +
        QString::number(fix_number(sd->toPlainText().toInt(),1,SMALLNOMAX,0)));
    this->showqsthmp_ans(isEditor);
}

void Form_qst::onchange_TreeCtrlTitle(){
    //标题变化
    auto sd = (QTextEdit*)sender();
    problem_title = sd->toPlainText();
    showqsthmp_ans(isEditor);
}

void Form_qst::on_but_back_clicked()
{
    stopTick_ans();
    if(isEditor){
        ui->stackedWidget->setCurrentIndex(0);
    }else{

    }

    ui->txtB_main->setHtml(ui->text_material->toPlainText());
}


void Form_qst::on_but_preview_clicked()
{

    if(ui->but_preview->text() == "HTML视图(&P)"){
        ui->stackedWidget_2->setCurrentIndex(0);
        ui->but_preview->setText("预览本题(&P)");
    }else{
        ui->but_preview->setText("HTML视图(&P)");
        ui->stackedWidget_2->setCurrentIndex(1);
    }


    ui->txtB_main->setHtml(ui->text_material->toPlainText());
}


void Form_qst::on_but_new_clicked()
{
    clearAll();
    bool ok;
    QString str1;

    unsigned int y = QInputDialog::getInt(0,"新建","请输入题目的题号 不填则将自动分配",-1,1,100000000,1,&ok);
    if(!ok || y == -1){
        auto now = QDateTime::currentDateTime();
        y = now.time().second();
        y += now.time().minute() * 60;
        y += now.time().hour() * 360;
        y += now.date().day() * 100000;
        y += now.date().month() * 10000000;
        y += now.date().year() * 10000000;

    }
    auto it = ui->tree_add->topLevelItem(0)->child(0);
    auto cb = (QTextEdit*)ui->tree_add->itemWidget(it,4);
    cb->setText(QString::number(y));

    str1 = QInputDialog::getText(0,"新建","请输入题目的标题",QLineEdit::Normal,QString(),&ok);
    if(ok && !str1.isEmpty()){
        //ui->text_title->setText(str1);
        cb = (QTextEdit*)ui->tree_add->itemWidget(it,1);
        cb->setText(str1);
    }


    str1 = QInputDialog::getItem(0,"新建","请选择题型",QList<QString>{"语法","阅读理解","单词","写作","翻译"},0,true,&ok);
    if(ok && !str1.isEmpty()){
        auto it = ui->tree_add->topLevelItem(0)->child(0);
        auto cb = (QComboBox*)ui->tree_add->itemWidget(it,2);
        cb->setCurrentText(str1);
    }


}

/**
 * @brief Form_qst::转至做题视图
 */
void Form_qst::on_but_cin_clicked()
{

    ui->stackedWidget_2->setCurrentIndex(1);
    ui->stackedWidget->setCurrentIndex(1);

    addqst_ans();       //装好问题
    startTick_ans();    //开始计时
    auto lst = ui->text_material->toPlainText().split(htmlsplitQA());   //隐藏答案
    ui->txtB_main->setHtml(lst[0]);
}


/**
 * @brief Form_qst::保存按钮
 */
void Form_qst::on_but_save_clicked()
{
    int ret = checkqst_ed();  //检查题目内容
    if(!ret){
        QMessageBox::warning(0,"提示","该题目无法保存");
        return;
    }
    saveqst_ed();   //保存题目内容
}


void Form_qst::on_text_material_textChanged()
{
    if(isChanged || !isEditor)return;
    QString now = windowTitle();
    now = "*" + now;
    setWindowTitle(now);
    isChanged = 1;
}

/**
 * @brief Form_qst::清空
 */
void Form_qst::on_pushButton_clicked()
{
    auto ret = QMessageBox::warning(0,"清空","您确定要清空所有数据吗？",QMessageBox::Yes | QMessageBox::No);
    if(ret != QMessageBox::Yes)return;
    clearAll();

}


/**
 * @brief Form_qst::保存答案获得成绩
 */
void Form_qst::save_grd(){
    //报告文件
    //保存记录和报告
    QString recf,htmlf,csvf,fn,hf,cf;
    char buf[2*FILENAME_MAX]={0};
    fn = rec_fname();
    getUserFilename(&set,FILENAME_RECORDS,buf);
    GETQSTRMB(recf,buf);
    recf = recf + "/" + fn;                 //文件路径

    htmlf = recf + ".html";                 //报告文件路径
    csvf = recf + ".csv";                   //记录文件路径

    save_file_string(htmlf,report_ans());       //保存报告文件
    save_file_string(csvf,record_ans());        //保存记录文件


    hf = fn + ".html";
    cf = fn + ".csv";                      //文件名

    emit send_save_grd(hf,cf);             //发送信号(文件名)

}

/**
 * @brief Form_qst::提交：计算分数 保存答案
 */
void Form_qst::on_but_calc_clicked()
{
    int t = ui->tree_ans->columnCount();
    if(t == 1){
        //题目文件有误
        QMessageBox::critical(0,"错误","题目格式有误！");
        return;
    }



    if(QMessageBox::warning(0,"提示","您确定提交吗 提交后将无法作答",QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)return;

    able_ans(0);                //停止作答
    stopTick_ans();             //停止计时
    calcscore_ans();            //算分

    //编辑时只改不保存 做题时会保存
    if(isEditor){
        QMessageBox::information(0,"生成报告",report_ans());
        QMessageBox::information(0,"记录文件",record_ans());
    }else{
        save_grd();                  //保存答案获得成绩
        QMessageBox::information(0,"提示","提交成功！");
        ui->but_calc->setDisabled(1);

    }


}


void Form_qst::on_but_open_clicked()
{
    openqst_ed();
}


void Form_qst::on_but_next_clicked()
{
    //下一个
}

void Form_qst::on_but_help_clicked()
{
    QMessageBox::information(0,"帮助",htmlheader_ans());
}


void Form_qst::on_but_help_triggered(QAction *arg1)
{

}

/**
 * @brief Form_qst::on_but_setscore_clicked
 */
void Form_qst::on_but_setscore_clicked()
{
    int qsts = ui->tree_add->topLevelItemCount();
    double num = QInputDialog::getDouble(0,"分数设置","每题几分？",5,0,SCOREMAX / (qsts-1));
    for(int i = 1;i < qsts;++i){
        auto t = ui->tree_add->topLevelItem(i)->child(0);
        auto w = (QTextEdit*)ui->tree_add->itemWidget(t,6);
        if(w){
            w->setText(QString::number(num));
        }
    }
}

